package me.uni.skyme.support;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.core.Ordered;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationObjectSupport;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;

public class SuffixViewResolver extends WebApplicationObjectSupport implements ViewResolver,Ordered{

	
	private int order=Ordered.HIGHEST_PRECEDENCE;
	
	private Map<String,ViewResolver> viewResolverMap;
	
	private Map<String,View> viewMap;
	
	private ViewResolver defualtViewResolver;
	
	private View defaultView;
	
	private boolean useNotAcceptableStatusCode = false;
	
	@Override
	public int getOrder() {
		return order;
	}

	
	
	
	public void setOrder(int order) {
		this.order = order;
	}




	public void setViewResolverMap(Map<String, ViewResolver> viewResolverMap) {
		this.viewResolverMap = viewResolverMap;
	}




	public void setViewMap(Map<String, View> viewMap) {
		this.viewMap = viewMap;
	}




	public void setDefualtViewResolver(ViewResolver defualtViewResolver) {
		this.defualtViewResolver = defualtViewResolver;
	}




	public void setDefaultView(View defaultView) {
		this.defaultView = defaultView;
	}




	public void setUseNotAcceptableStatusCode(boolean useNotAcceptableStatusCode) {
		this.useNotAcceptableStatusCode = useNotAcceptableStatusCode;
	}




	@Override
	public View resolveViewName(String viewName, Locale locale) throws Exception {
		
		RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
		Assert.isInstanceOf(ServletRequestAttributes.class, attrs);
		ServletRequestAttributes servletAttrs = (ServletRequestAttributes) attrs;
		
		
		Map<String,View> candidateViewMap = new HashMap<String,View>();
		for (Entry<String, ViewResolver> entry : this.viewResolverMap.entrySet()) {
			View view = entry.getValue().resolveViewName(viewName, locale);
			if (view != null) {
				candidateViewMap.put(entry.getKey(), view);
			}
		}
		if (!CollectionUtils.isEmpty(this.viewMap)) {
			candidateViewMap.putAll(this.viewMap);
		}
		
		
		
		View bestView=null;
		String uri=servletAttrs.getRequest().getRequestURI();

		if(StringUtils.hasText(uri))
		{
			for(Entry<String,View> entry:candidateViewMap.entrySet())
			{
				if (StringUtils.endsWithIgnoreCase(uri, entry.getKey())) {
					bestView=entry.getValue();
					break;
				}
			}
		}
		
		
		if(bestView==null)
		{
			if(defualtViewResolver!=null)
			{
				bestView=defualtViewResolver.resolveViewName(viewName, locale);
			}
			if(bestView==null)
			{
				if(defaultView!=null)
				{
					bestView=defaultView;
				}
			}
		}
		
		
		if (bestView != null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Returning [" + bestView + "]");
			}
			return bestView;
		}
		else {
			if (useNotAcceptableStatusCode) {
				if (logger.isDebugEnabled()) {
					logger.debug("No acceptable view found; returning 406 (Not Acceptable) status code");
				}
				return NOT_ACCEPTABLE_VIEW;
			}
			else {
				if (logger.isDebugEnabled()) {
					logger.debug("No acceptable view found; returning null");
				}
				return null;
			}
		}
	}
	
	private static final View NOT_ACCEPTABLE_VIEW = new View() {

		public String getContentType() {
			return null;
		}

		public void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response)
				throws Exception {
			response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
		}
	};
}
